home *** CD-ROM | disk | FTP | other *** search
/ World of Video / World of Video.iso / gfxprograms / 3dprograms / rayshade-4.0 / rayview / glmethods.c next >
C/C++ Source or Header  |  1995-02-13  |  21KB  |  1,043 lines

  1. /*
  2.  * glmethods.c
  3.  *
  4.  * Support routines for SGI/RS6000 machines.
  5.  *
  6.  * Copyright (C) 1989, 1991, Craig E. Kolb, Allan Snyder
  7.  *
  8.  * This software may be freely copied, modified, and redistributed
  9.  * provided that this copyright notice is preserved on all copies.
  10.  *
  11.  * You may not distribute this software, in whole or in part, as part of
  12.  * any commercial product without the express consent of the authors.
  13.  * 
  14.  * There is no warranty or other guarantee of fitness of this software
  15.  * for any purpose.  It is provided solely "as is".
  16.  *
  17.  * glmethods.c,v 4.1 1994/08/09 08:07:59 explorer Exp
  18.  *
  19.  * glmethods.c,v
  20.  * Revision 4.1  1994/08/09  08:07:59  explorer
  21.  * Bump version to 4.1
  22.  *
  23.  * Revision 1.1.1.1  1994/08/08  04:52:29  explorer
  24.  * Initial import.  This is a prerelease of 4.0.6enh3, or 4.1 possibly.
  25.  *
  26.  * Revision 4.0.1.4  92/01/10  17:17:39  cek
  27.  * patch3: Added heightfield support.
  28.  * 
  29.  * Revision 4.0.1.3  91/12/13  11:43:11  cek
  30.  * patch3: Spot direction and spread now set correctly.
  31.  * patch3: Set GLC_OLDPOLYGON to 0 on sgi machines to fix VGX weirdness.
  32.  * 
  33.  * Revision 4.0.1.2  91/10/10  22:45:27  cek
  34.  * patch1: Added spotlight support.
  35.  * 
  36.  * Revision 4.0.1.1  1991/09/29  15:28:36  cek
  37.  * patch1: Added support for transparency.
  38.  *
  39.  * Revision 4.0  91/07/17  17:38:43  kolb
  40.  * Initial version
  41.  * 
  42.  */
  43. #include <gl.h>
  44. #include <device.h>
  45. #include "rayshade.h" 
  46. #include "options.h"
  47. #include "viewing.h"
  48.  
  49. #include "libsurf/surface.h"
  50.  
  51. #include "libobj/box.h"
  52. #include "libobj/cone.h"
  53. #include "libobj/csg.h"
  54. #include "libobj/cylinder.h"
  55. #include "libobj/disc.h"
  56. #include "libobj/hf.h"
  57. #include "libobj/grid.h"
  58. #include "libobj/instance.h"
  59. #include "libobj/list.h"
  60. #include "libobj/plane.h"
  61. #include "libobj/poly.h"
  62. #include "libobj/sphere.h"
  63. #include "libobj/triangle.h"
  64.  
  65. #include "liblight/light.h"
  66. #include "liblight/extended.h"
  67. #include "liblight/infinite.h"
  68. #include "liblight/point.h"
  69. #include "liblight/spot.h"
  70.  
  71. #define CIRCLE_SAMPLES    20    /* # of samples around circle (cone/cyl/etc) */
  72. #define DEFAULT_NEAR    .2    /* default value for near clipping plane */
  73. #define DEFAULT_FAR    350.    /* default far clipping plane */
  74. #define PLANE_RAD    450.    /* radius of disc used to represent planes */
  75.  
  76. #ifndef SPHERELIB
  77. #define SPHERE_LEVEL    3
  78. #endif
  79.  
  80. /*
  81.  * Pass a normal stored in a Vector to the geometry pipeline.
  82.  */
  83. #define GLNormal(w)    (glnrm[0] = (w)->x, glnrm[1] = (w)->y, \
  84.              glnrm[2] = (w)->z, n3f(glnrm))
  85.  
  86. static void    GLBoxDraw(), GLConeDraw(), GLCsgDraw(), GLCylinderDraw(),
  87.         GLDiscDraw(),
  88.         GLGridDraw(), GLHfDraw(), GLInstanceDraw(),    
  89.         GLListDraw(), GLPlaneDraw(), GLPolygonDraw(),
  90.         GLSphereDraw(), GLTorusDraw(), GLTriangleDraw(),
  91.         GLBoundsDraw(),
  92.         GLInfiniteLight(), GLPointLight(), GLSpotLight(),
  93.         GLExtendedLight();
  94.  
  95. static short    cursurf = 1,
  96.         curlight = 1;
  97.  
  98. static Object    GLBoxObject,
  99.         GLCylObject,
  100.         GLSphereObject,
  101.         GLBoxObjectDefine(),
  102.         GLCylObjectDefine();
  103.  
  104. extern Object    GLSphereObjectDefine();
  105.  
  106. static int    Doublebuffered;
  107.  
  108. static float    Ident[4][4] =    {1., 0., 0., 0.,
  109.                  0., 1., 0., 0.,
  110.                  0., 0., 1., 0.,
  111.                  0., 0., 0., 1.},
  112.         glnrm[3];
  113.  
  114. static float **CirclePoints;
  115.  
  116. static void LightDraw(), GeomDraw(), GLMultMatrix(),
  117.         GLPushSurface(), GLPopSurface(), LightDrawInit(),
  118.         ObjectInit(), GLDrawFrame(), ScreenDrawInit(), DrawInit(),
  119.         GLUnitCircle(), GLDisc(), ComputeClippingPlanes();
  120.  
  121. Float CurrentTime;
  122.  
  123. static unsigned long BackPack;    /* Packed background color */
  124. static long Zinit;        /* maximum Zbuffer value */
  125.  
  126. MethodsRegister()
  127. {
  128.     BoxMethodRegister(GLBoxDraw);
  129.     ConeMethodRegister(GLConeDraw);
  130.     CsgMethodRegister(GLCsgDraw);
  131.     CylinderMethodRegister(GLCylinderDraw);
  132.     DiscMethodRegister(GLDiscDraw);
  133.     GridMethodRegister(GLGridDraw);
  134. #ifdef sgi
  135.     HfMethodRegister(GLHfDraw);
  136. #endif
  137.     InstanceMethodRegister(GLInstanceDraw);
  138.     ListMethodRegister(GLListDraw);
  139.     PlaneMethodRegister(GLPlaneDraw);
  140.     PolygonMethodRegister(GLPolygonDraw);
  141.     SphereMethodRegister(GLSphereDraw);
  142.     /*TorusMethodRegister(GLTorusDraw);*/
  143.     TriangleMethodRegister(GLTriangleDraw);
  144.  
  145.     InfiniteMethodRegister(GLInfiniteLight);
  146.     PointMethodRegister(GLPointLight);
  147.     ExtendedMethodRegister(GLExtendedLight);
  148.     SpotMethodRegister(GLSpotLight);
  149. }
  150.  
  151. void
  152. Render()
  153. {
  154.     short val;
  155.     float tmp;
  156.  
  157.     /*
  158.      * We're only sampling the scene once, so we need
  159.      * not do lots of work to determine exactly what
  160.      * animated transformations are doing...
  161.      */
  162.     Options.samples = 1;
  163.     SamplingSetOptions(Options.samples, Options.gaussian,
  164.                Options.filterwidth);
  165.  
  166.     DrawInit();
  167.     qdevice(ESCKEY);
  168.     qdevice(SPACEKEY);
  169.     qdevice(REDRAW);
  170.  
  171.     DrawFrames();
  172.  
  173.     while (TRUE) {
  174.         switch (qread(&val)) {
  175.             case ESCKEY:
  176.                 exit(0);
  177.                 break;
  178.             case REDRAW:
  179.                 reshapeviewport();
  180.                 DrawFrames();
  181.                 break;
  182.             case SPACEKEY:
  183.                 if (!val)
  184.                     DrawFrames();
  185.                 break;
  186.         }
  187.     }
  188. }
  189.  
  190. DrawFrames()
  191. {
  192.     int i;
  193.     for (i = 0; i < Options.totalframes; i++)
  194.         GLDrawFrame(i);
  195. }
  196.  
  197. static void
  198. DrawInit()
  199. {
  200.     extern Surface DefaultSurface;
  201.  
  202.     ScreenDrawInit();
  203.     ObjectInit();
  204.     LightDrawInit();
  205.  
  206.     /*
  207.      * Push the default surface.
  208.      */
  209.     GLPushSurface(&DefaultSurface);
  210. }
  211.  
  212. static void
  213. ScreenDrawInit()
  214. {
  215.     /*
  216.      * Open window, initialize graphics, etc.
  217.      */
  218. #ifdef sgi
  219.     foreground();
  220. #endif
  221.     prefsize(Screen.xsize, Screen.ysize);
  222.     winopen("rayview");
  223.  
  224. #ifdef sgi
  225.     glcompat(GLC_OLDPOLYGON, 0);
  226. #endif
  227.  
  228.     RGBmode();
  229.     mmode(MVIEWING);
  230.  
  231.     if (Options.totalframes > 1) {
  232.         Doublebuffered = TRUE;
  233.         doublebuffer();
  234.     }
  235.  
  236.  
  237.     gconfig();
  238.     blendfunction(BF_SA, BF_MSA);
  239.     zbuffer(TRUE);
  240.  
  241.     /*
  242.      * Initialize viewing matrix.
  243.      */
  244.     GLViewingInit();
  245.  
  246.     BackPack = (unsigned char)(255*Screen.background.r) |
  247.         ((unsigned char)(255*Screen.background.g) << 8) |
  248.         ((unsigned char)(255*Screen.background.b) << 16);
  249.     Zinit = getgdesc(GD_ZMAX);
  250.     lsetdepth(0, Zinit);
  251. }
  252.  
  253. /*
  254.  * Draw the World object.
  255.  */
  256. static void
  257. GLDrawFrame(frame)
  258. int frame;
  259. {
  260.     extern Geom *World;
  261.  
  262.     RSStartFrame(frame);
  263.     CurrentTime = Options.framestart;
  264.     TimeSet(CurrentTime);
  265.  
  266.     czclear(BackPack, Zinit);    
  267.  
  268.     /*
  269.      * Draw the World object
  270.      */
  271.     GeomDraw(World);
  272.     if (Doublebuffered)
  273.         swapbuffers();
  274. }
  275.  
  276. GLViewingInit()
  277. {
  278.     float near, far, aspect, dist, T[4][4];
  279.     short ang;
  280.     extern Geom *World;
  281.  
  282.     ang = Camera.vfov * 10 + 0.5;
  283.     aspect = Camera.hfov / Camera.vfov;
  284.  
  285.     T[0][0]=Screen.scrni.x; T[0][1]=Screen.scrnj.x; T[0][2]= -Camera.dir.x;
  286.     T[1][0]=Screen.scrni.y; T[1][1]=Screen.scrnj.y; T[1][2]= -Camera.dir.y;
  287.     T[2][0]=Screen.scrni.z; T[2][1]=Screen.scrnj.z; T[2][2]= -Camera.dir.z;
  288.  
  289.     T[0][3] = T[1][3] = T[2][3] = 0.;
  290.  
  291.     T[3][0] = -dotp(&Camera.lookp, &Screen.scrni);
  292.     T[3][1] = -dotp(&Camera.lookp, &Screen.scrnj);
  293.     T[3][2] = dotp(&Camera.lookp, &Camera.dir);
  294.     T[3][3] = 1.;
  295.  
  296.     ComputeClippingPlanes(&near, &far, World->bounds);
  297.  
  298.     loadmatrix(Ident);
  299.     perspective(ang, aspect, near, far);
  300.     polarview((float)Camera.lookdist, 0, 0, 0);
  301.     multmatrix(T);
  302. }
  303.  
  304.  
  305. static void
  306. ObjectInit()
  307. {
  308.     CircleDefine();
  309.     GLBoxObject = GLBoxObjectDefine();
  310.  
  311. #ifdef SPHERELIB
  312.     GLSphereObject = GLSphereObjectDefine();
  313. #else
  314.     GLSphereObject = GLSphereObjectDefine(SPHERE_LEVEL);
  315. #endif
  316.  
  317.     GLCylObject = GLCylObjectDefine();
  318. }
  319.  
  320. static void
  321. GeomDraw(obj)
  322. Geom *obj;
  323. {
  324.     Trans *ct;
  325.     /*
  326.      * If object has a surface associated with it,
  327.      * start using it.
  328.      */
  329.     if (obj->surf)
  330.         GLPushSurface(obj->surf);
  331.     if (obj->trans) {
  332.         /*
  333.          * Take care of any animated transformations that
  334.          * exist.
  335.          */
  336.         if (obj->animtrans && !equal(obj->timenow, CurrentTime)) {
  337.             TransResolveAssoc(obj->trans);
  338.             obj->timenow = CurrentTime;
  339.         }
  340.         pushmatrix();
  341.         /*
  342.           * Apply in reverse order.
  343.          */
  344.         for (ct = obj->transtail; ct; ct = ct->prev)
  345.             GLMultMatrix(&ct->trans);
  346.     }
  347.  
  348.     if (obj->methods->user) {
  349.         /*
  350.           * Call proper method
  351.           */
  352.         (*obj->methods->user)(obj->obj);
  353.     } else {
  354.         /*
  355.          * Draw bounding box.
  356.          */
  357.         GLBoundsDraw(obj->bounds);
  358.     }
  359.  
  360.     if (obj->surf)
  361.         GLPopSurface();
  362.     if (obj->trans)
  363.         popmatrix();
  364. }
  365.  
  366. static float surfprops[] =    {AMBIENT, 0, 0, 0,
  367.                  DIFFUSE, 0, 0, 0,
  368.                  SPECULAR, 0, 0, 0,
  369.                  SHININESS, 0,
  370.                  ALPHA, 1,
  371.                  LMNULL};
  372. static float    *amb = &surfprops[1],
  373.         *diff = &surfprops[5],
  374.         *spec = &surfprops[9],
  375.         *shine = &surfprops[13],
  376.         *alpha = &surfprops[15];
  377.  
  378. static void
  379. GLPushSurface(surf)
  380. Surface *surf;
  381. {
  382.     static Surface *lastsurf = NULL;
  383.  
  384.     /*
  385.      * Start using the given surface.
  386.      * In the case of the use of an "applysurf",
  387.      * the same surface will be applied to many
  388.      * primitives individually.  By saving the
  389.      * pointer to the last surface, we keep from
  390.      * lmdef'ing the surface when we don't need to.
  391.      */
  392.     if (surf != lastsurf) {
  393.         amb[0] = surf->amb.r; amb[1] = surf->amb.g;
  394.             amb[2] = surf->amb.b;
  395.         diff[0] = surf->diff.r; diff[1] = surf->diff.g;
  396.             diff[2] = surf->diff.b;
  397.         spec[0] = surf->spec.r; spec[1] = surf->spec.g;
  398.             spec[2] = surf->spec.b;
  399.         shine[0] = surf->srexp;
  400.         *alpha = 1. - surf->transp;
  401.         lmdef(DEFMATERIAL, cursurf, sizeof(surfprops)/sizeof(float),
  402.             surfprops);
  403.         lastsurf = surf;
  404.     }
  405.     lmbind(MATERIAL, cursurf);
  406.     cursurf++;
  407. }
  408.  
  409. static void
  410. GLMultMatrix(trans)
  411. RSMatrix *trans;
  412. {
  413.     float newmat[4][4];
  414.     /*
  415.      * Multiply in the given transformation.
  416.      */
  417.     newmat[0][0] = trans->matrix[0][0]; newmat[0][1] = trans->matrix[0][1];
  418.     newmat[0][2] = trans->matrix[0][2]; newmat[0][3] = 0.;
  419.     newmat[1][0] = trans->matrix[1][0]; newmat[1][1] = trans->matrix[1][1];
  420.     newmat[1][2] = trans->matrix[1][2]; newmat[1][3] = 0.;
  421.     newmat[2][0] = trans->matrix[2][0]; newmat[2][1] = trans->matrix[2][1];
  422.     newmat[2][2] = trans->matrix[2][2]; newmat[2][3] = 0.;
  423.     newmat[3][0] = trans->translate.x; newmat[3][1] = trans->translate.y;
  424.     newmat[3][2] = trans->translate.z ; newmat[3][3] = 1.;
  425.     multmatrix(newmat);
  426. }
  427.  
  428. static void
  429. GLPopSurface()
  430. {
  431.     cursurf--;
  432.     lmbind(MATERIAL, cursurf-1);
  433. }
  434.  
  435. static void
  436. GLBoundsDraw(bounds)
  437. Float bounds[2][3];
  438. {
  439.     float sx, sy, sz;
  440.  
  441.     pushmatrix();
  442.  
  443.     translate(bounds[LOW][X], bounds[LOW][Y], bounds[LOW][Z]);
  444.     scale(    bounds[HIGH][X] - bounds[LOW][X],
  445.         bounds[HIGH][Y] - bounds[LOW][Y],
  446.         bounds[HIGH][Z] - bounds[LOW][Z]);
  447.     pushmatrix();
  448.     callobj(GLBoxObject);
  449.     popmatrix();
  450.     popmatrix();
  451. }
  452.  
  453. static void
  454. GLBoxDraw(box)
  455. Box *box;
  456. {
  457.     GLBoundsDraw(box->bounds);
  458. }
  459.  
  460.  
  461. static void
  462. GLConeDraw(cone)
  463. Cone *cone;
  464. {
  465.     int i, j;
  466.     float norm[3], normconst, ZeroVect[3], tmpv[3];
  467.  
  468.     ZeroVect[0] = ZeroVect[1] = ZeroVect[2] = 0.;
  469.     /*
  470.      * Sides.
  471.      * For the normal, assume we are finding the normal at
  472.      * (C_P[i].x, C_P[i].y, 1.) at this point, the unnormalized
  473.      * normal = (C_P[i].x, C_P[i].y, -tantheta^2).  When we normalize,
  474.      * then length of the vector is simply equal to:
  475.      * sqrt(CP[i].x^2 + CP[i].y^2 + tantheta^4)  ==
  476.      * sqrt(1. + tantheta^4)
  477.      * In our case, tantheta = 1., so...
  478.      */
  479.  
  480.     normconst = 1. / sqrt(2.);
  481.     norm[2] = -normconst;
  482.  
  483.     pushmatrix();
  484.     GLMultMatrix(&cone->trans.trans);
  485.  
  486.     for (i = 0; i < CIRCLE_SAMPLES; i++) {
  487.         j = (i + 1) % CIRCLE_SAMPLES;
  488.         norm[0] = CirclePoints[i][0] * normconst;
  489.         norm[1] = CirclePoints[i][1] * normconst;
  490.         n3f(norm);
  491.         bgnpolygon();
  492.         if (cone->start_dist > EPSILON) {
  493.             tmpv[2] = cone->start_dist;
  494.             tmpv[0] = CirclePoints[i][0] * cone->start_dist;
  495.             tmpv[1] = CirclePoints[i][1] * cone->start_dist;
  496.             v3f(tmpv);
  497.             tmpv[0] = CirclePoints[j][0] * cone->start_dist;
  498.             tmpv[1] = CirclePoints[j][1] * cone->start_dist;
  499.             v3f(tmpv);
  500.         } else
  501.             v3f(ZeroVect);
  502.         tmpv[2] = 1.;
  503.         tmpv[0] = CirclePoints[j][0];
  504.         tmpv[1] = CirclePoints[j][1];
  505.         v3f(tmpv);
  506.         tmpv[0] = CirclePoints[i][0];
  507.         tmpv[1] = CirclePoints[i][1];
  508.         v3f(tmpv);
  509.         endpolygon();
  510.     }
  511.     popmatrix();
  512. }
  513.  
  514. static void
  515. GLCsgDraw(csg)
  516. Csg *csg;
  517. {
  518.     /*
  519.      * Punt by drawing both objects.
  520.      */
  521.     GeomDraw(csg->obj1);
  522.     GeomDraw(csg->obj2);
  523. }
  524.  
  525. static void
  526. GLCylinderDraw(cyl)
  527. Cylinder *cyl;
  528. {
  529.     pushmatrix();
  530.     GLMultMatrix(&cyl->trans.trans);
  531.     callobj(GLCylObject);
  532.     popmatrix();
  533. }
  534.  
  535. static void
  536. GLDiscDraw(disc)
  537. Disc *disc;
  538. {
  539.     GLDisc((Float)sqrt(disc->radius), &disc->pos, &disc->norm);
  540. }
  541.  
  542. static void
  543. GLDisc(rad, pos, norm)
  544. Float rad;
  545. Vector *pos, *norm;
  546. {
  547.     RSMatrix m, tmp;
  548.     Vector atmp;
  549.  
  550.     /*
  551.      * This is kinda disgusting...
  552.      */
  553.     ScaleMatrix(rad, rad, 1., &m);
  554.     if (fabs(norm->z) == 1.) {
  555.         atmp.x = 1.;
  556.         atmp.y = atmp.z = 0.;
  557.     } else {
  558.         atmp.x = norm->y;
  559.         atmp.y = -norm->x;
  560.         atmp.z= 0.;
  561.     }
  562.  
  563.     RotationMatrix(atmp.x, atmp.y, atmp.z, -acos(norm->z), &tmp);
  564.     MatrixMult(&m, &tmp, &m);
  565.     TranslationMatrix(pos->x, pos->y, pos->z, &tmp);
  566.     MatrixMult(&m, &tmp, &m);
  567.     pushmatrix();
  568.     GLMultMatrix(&m);
  569.     /*
  570.      * Draw unit circle.
  571.      */
  572.     GLUnitCircle(0., TRUE);
  573.     popmatrix();
  574. }
  575.  
  576. static void
  577. GLGridDraw(grid)
  578. Grid *grid;
  579. {
  580.     Geom *ltmp;
  581.  
  582.     for (ltmp = grid->unbounded; ltmp; ltmp = ltmp->next)
  583.         GeomDraw(ltmp);
  584.     for (ltmp = grid->objects; ltmp; ltmp = ltmp->next)
  585.         GeomDraw(ltmp);
  586. }
  587.  
  588. static void
  589. GLHfDraw(hf)
  590. Hf *hf;
  591. {
  592.     int x, y;
  593.     float n[3], v[3], del, del2, del4, dz1, delz, za, zb, zc;
  594.     float bot, top, left, right, len;
  595.  
  596.     del = 1. / (hf->size - 1);
  597.     del2 = del*del;
  598.     del4 = del2*del2;
  599.  
  600.     bot = 0.;
  601.     top = del;
  602.  
  603.     for (y = 0; y < hf->size -1; y++) {
  604.         za = hf->data[y+1][0];
  605.         zb = hf->data[y][0];
  606.         left = 0;
  607.         right = del;
  608.         for (x = 1; x < hf->size; x++) {
  609.             /*
  610.              * A +-+ C
  611.              *   |/
  612.              * B +
  613.              */
  614.         
  615.             zc = hf->data[y+1][x];
  616.             dz1 = za - zb;
  617.             delz = za - zc;
  618.             len = sqrt(del2*delz*delz + del2*dz1*dz1 + del4);
  619.             bgnpolygon();
  620.             n[0] = del*delz/len;
  621.             n[1] = -del*dz1/len;
  622.             n[2] = del2/len;
  623.             n3f(n);
  624.             v[0] = left; v[1] = top; v[2] = za; v3f(v);
  625.             v[1] = bot; v[2] = zb; v3f(v);
  626.             v[0] = right; v[1] = top; v[2] = zc; v3f(v);
  627.             endpolygon();
  628.  
  629.             /*
  630.              *   B +
  631.              *    /|
  632.              * A +-+ C
  633.              */
  634.             za = zb; zb = zc; zc = hf->data[y][x];
  635.             dz1 = zc - za;
  636.             delz = zc - zb;
  637.             len = sqrt(del2*dz1*dz1 + del2*delz*delz + del4);
  638.             n[0] = -del*dz1/len;
  639.             n[1] = del*delz/len;
  640.             n[2] = del2/len;
  641.             bgnpolygon();
  642.             n3f(n);
  643.             v[0] = left; v[1] = bot; v[2] = za; v3f(v);
  644.             v[0] = right; v[2] = zc; v3f(v);
  645.             v[1] = top; v[2] = zb; v3f(v);
  646.             endpolygon();
  647.             left = right;
  648.             right += del;
  649.             za = zb;
  650.             zb = zc;
  651.         }
  652.         bot = top;
  653.         top += del;
  654.     }
  655.     
  656. }
  657.  
  658. static void
  659. GLInstanceDraw(inst)
  660. Instance *inst;
  661. {
  662.     GeomDraw(inst->obj);
  663. }
  664.  
  665. static void
  666. GLListDraw(list)
  667. List *list;
  668. {
  669.     Geom *ltmp;
  670.  
  671.     for (ltmp = list->unbounded; ltmp; ltmp = ltmp->next)
  672.         GeomDraw(ltmp);
  673.     for (ltmp = list->list; ltmp; ltmp = ltmp->next)
  674.         GeomDraw(ltmp);
  675. }
  676.  
  677. static void
  678. GLPlaneDraw(plane)
  679. Plane *plane;
  680. {
  681.     /*
  682.      * Draw a really big disc.
  683.      */
  684.     GLDisc((Float)PLANE_RAD, &plane->pos, &plane->norm);
  685. }
  686.  
  687. static void
  688. GLPolygonDraw(poly)
  689. register Polygon *poly;
  690. {
  691.     register int i;
  692.  
  693.     GLNormal(&poly->norm);
  694.  
  695.     bgnpolygon();
  696.     for (i = 0; i < poly->npoints; i++)
  697.         v3d(&poly->points[i]);
  698.     endpolygon();
  699. }
  700.  
  701. static void
  702. GLSphereDraw(sph)
  703. Sphere *sph;
  704. {
  705.     pushmatrix();
  706.     translate(sph->x, sph->y, sph->z);
  707.     scale(sph->r, sph->r, sph->r);
  708.     callobj(GLSphereObject);
  709.     popmatrix();
  710. }
  711.  
  712. static void
  713. GLTorusDraw(){}
  714.  
  715. static void
  716. GLTriangleDraw(tri)
  717. register Triangle *tri;
  718. {
  719.     /*
  720.      * If Float is a double, use v3d,
  721.      * otherwise use v3f.
  722.      */
  723.     if (tri->type != PHONGTRI) {
  724.         GLNormal(&tri->nrm);    
  725.         bgnpolygon();
  726.         v3d(&tri->p[0]); v3d(&tri->p[1]); v3d(&tri->p[2]);
  727.         endpolygon();
  728.     } else {
  729.         bgnpolygon();
  730.         GLNormal(&tri->vnorm[0]);
  731.         v3d(&tri->p[0]);
  732.         GLNormal(&tri->vnorm[1]);
  733.         v3d(&tri->p[1]);
  734.         GLNormal(&tri->vnorm[2]);
  735.         v3d(&tri->p[2]);
  736.         endpolygon();
  737.     }
  738. }
  739.  
  740. float lightprops[] =    {POSITION, 0., 0., 0., 0.,
  741.              LCOLOR, 0, 0, 0,
  742.              SPOTDIRECTION, 0., 0., 0.,
  743.              SPOTLIGHT, 0., 180.,
  744.              LMNULL};
  745.  
  746. float     *lpos = &lightprops[1],
  747.     *lcolor = &lightprops[6],
  748.     *spotdir = &lightprops[10],
  749.     *spotexp = &lightprops[14],
  750.     *spotspread = &lightprops[15];
  751.  
  752. float lmodel[] =    {AMBIENT, 1., 1., 1.,
  753.              ATTENUATION, 1., 0.,
  754.              LOCALVIEWER, 0.,
  755. #ifdef sgi
  756.              ATTENUATION2, 0.,
  757.              TWOSIDE, 1.,
  758. #endif
  759.              LMNULL};
  760.  
  761. static void
  762. LightDrawInit()
  763. {
  764.     Light *light;
  765.     extern Light *Lights;
  766.  
  767.     for (light = Lights; light; light = light->next)
  768.         LightDraw(light);
  769.  
  770.     switch (curlight-1) {
  771.         case 8:
  772.             lmbind(LIGHT7, 8);
  773.         case 7:
  774.             lmbind(LIGHT6, 7);
  775.         case 6:
  776.             lmbind(LIGHT5, 6);
  777.         case 5:
  778.             lmbind(LIGHT4, 5);
  779.         case 4:
  780.             lmbind(LIGHT3, 4);
  781.         case 3:
  782.             lmbind(LIGHT2, 3);
  783.         case 2:
  784.             lmbind(LIGHT1, 2);
  785.         case 1:
  786.             lmbind(LIGHT0, 1);
  787.     }
  788.  
  789.     lmodel[1] = Options.ambient.r;
  790.     lmodel[2] = Options.ambient.g;
  791.     lmodel[3] = Options.ambient.b;
  792.  
  793.     lmdef(DEFLMODEL, 1, sizeof(lmodel) / sizeof(float), lmodel);
  794.     lmbind(LMODEL, 1);
  795. }
  796.  
  797. static void
  798. LightDraw(light)
  799. Light *light;
  800. {
  801.     if (!light || !light->methods->user)
  802.         return;
  803.     lcolor[0] = light->color.r;
  804.     lcolor[1] = light->color.g;
  805.     lcolor[2] = light->color.b;
  806.     (*light->methods->user)(light->light);
  807. }
  808.  
  809. static void
  810. GLExtendedLight(ext)
  811. Extended *ext;
  812. {
  813.     lpos[0] = ext->pos.x;
  814.     lpos[1] = ext->pos.y;
  815.     lpos[2] = ext->pos.z;
  816.     lpos[3] = 1.;
  817.     lmdef(DEFLIGHT, curlight++, sizeof(lightprops)/sizeof(float),
  818.         lightprops);
  819. }
  820.  
  821.  
  822. static void
  823. GLInfiniteLight(inf)
  824. Infinite *inf;
  825. {
  826.     lpos[0] = inf->dir.x;
  827.     lpos[1] = inf->dir.y;
  828.     lpos[2] = inf->dir.z;
  829.     lpos[3] = 0.;
  830.     lmdef(DEFLIGHT, curlight++, sizeof(lightprops)/sizeof(float),
  831.         lightprops);
  832. }
  833.  
  834. static void
  835. GLPointLight(pt)
  836. Pointlight *pt;
  837. {
  838.     lpos[0] = pt->pos.x;
  839.     lpos[1] = pt->pos.y;
  840.     lpos[2] = pt->pos.z;
  841.     lpos[3] = 1.;
  842.     lmdef(DEFLIGHT, curlight++, sizeof(lightprops) / sizeof(float),
  843.             lightprops);
  844. }
  845.  
  846. static void
  847. GLSpotLight(spot)
  848. Spotlight *spot;
  849. {
  850.     lpos[0] = spot->pos.x;
  851.     lpos[1] = spot->pos.y;
  852.     lpos[2] = spot->pos.z;
  853.     lpos[3] = 1.;
  854.     spotdir[0] = spot->dir.x;
  855.     spotdir[1] = spot->dir.y;
  856.     spotdir[2] = spot->dir.z;
  857.     *spotexp = spot->coef;
  858.     *spotspread = 180 * acos(spot->falloff) / PI;
  859.     lmdef(DEFLIGHT, curlight++, sizeof(lightprops) / sizeof(float),
  860.             lightprops);
  861.     /* fix up spot defs so other source methods needn't reset them. */
  862.     *spotspread = 180.;
  863.     *spotexp = 1.;
  864. }
  865.  
  866. static float boxfaces[6][4][3] = {
  867. {     {1., 1., 1.},
  868.     {0., 1., 1.},
  869.     {0., 0., 1.},
  870.     {1., 0., 1.}    },
  871. {    {1., 0., 1.},
  872.     {0., 0., 1.},
  873.     {0., 0., 0.},
  874.     {1., 0., 0.}    },
  875. {    {1., 0., 0.},
  876.     {0., 0., 0.},
  877.     {0., 1., 0.},
  878.     {1., 1., 0.}    },
  879. {    {0., 1., 0.},
  880.     {0., 1., 1.},
  881.     {1., 1., 1.},
  882.     {1., 1., 0.}    },
  883. {    {1., 1., 1.},
  884.     {1., 0., 1.},
  885.     {1., 0., 0.},
  886.     {1., 1., 0.}    },
  887. {    {0., 0., 1.},
  888.     {0., 1., 1.},
  889.     {0., 1., 0.},
  890.     {0., 0., 0.}}};
  891.  
  892. float boxnorms[6][3] = {
  893.     {0, 0, 1},
  894.     {0, -1, 0},
  895.     {0, 0, -1},
  896.     {0, 1, 0},
  897.     {1, 0, 0,},
  898.     {-1, 0, 0}};
  899.  
  900. /*
  901.  * Define a unit cube centered at (0.5, 0.5, 0.5)
  902.  */
  903. static Object
  904. GLBoxObjectDefine()
  905. {
  906.     int i, box;
  907.  
  908.     makeobj(box = genobj());
  909.     for (i = 0; i < 6; i++)    {
  910.         n3f(boxnorms[i]);
  911.         polf(4, boxfaces[i]);
  912.     }
  913.     closeobj();
  914.     return box;
  915. }
  916.  
  917. static void
  918. GLUnitCircle(z, up)
  919. float z;
  920. int up;
  921. {
  922.     int i;
  923.     float norm[3];
  924.  
  925.     norm[0] = norm[1] = 0.;
  926.     bgnpolygon();
  927.  
  928.     if (up) {
  929.         norm[2] = 1.;
  930.         n3f(norm);    
  931.         for (i = 0; i < CIRCLE_SAMPLES; i++) {
  932.             CirclePoints[i][2] = z;
  933.             v3f(CirclePoints[i]);
  934.         }
  935.     } else {
  936.         norm[2] = -1.;
  937.         n3f(norm);    
  938.         for (i = CIRCLE_SAMPLES -1; i; i--) {
  939.             CirclePoints[i][2] = z;
  940.             v3f(CirclePoints[i]);
  941.         }
  942.     }
  943.  
  944.     endpolygon();
  945. }
  946.  
  947. static Object
  948. GLCylObjectDefine()
  949. {
  950.     int i, j, cyl;
  951.     float norm[3];
  952.  
  953.     makeobj(cyl = genobj());
  954.     norm[2] = 0;
  955.     for (i = 0; i < CIRCLE_SAMPLES; i++) {
  956.         j = (i+1)%CIRCLE_SAMPLES;
  957.         norm[0] = CirclePoints[i][0];
  958.         norm[1] = CirclePoints[i][1];
  959. #ifdef sgi
  960.         n3f(norm);
  961.         bgnpolygon();
  962.         CirclePoints[i][2] = 0;
  963.         v3f(CirclePoints[i]);
  964.         CirclePoints[j][2] = 0;
  965.         v3f(CirclePoints[j]);
  966.         CirclePoints[j][2] = 1;
  967.         v3f(CirclePoints[j]);
  968.         CirclePoints[i][2] = 1;
  969.         v3f(CirclePoints[i]);
  970.         endpolygon();
  971. #else
  972.         n3f(norm);
  973.         pmv(CirclePoints[i][0], CirclePoints[i][1], 0.);
  974.         pdr(CirclePoints[j][0], CirclePoints[j][1], 0.);
  975.         pdr(CirclePoints[j][0], CirclePoints[j][1], 1.);
  976.         pdr(CirclePoints[i][0], CirclePoints[i][1], 1.);
  977.         pclos();
  978. #endif
  979.     }
  980.     closeobj();
  981.     return cyl;
  982. }
  983.  
  984. /*
  985.  * Fill CirclePoints[t] with X and Y values cooresponding to points
  986.  * along the unit circle.  The size of CirclePoints is equal to
  987.  * CIRCLE_SAMPLES.
  988.  */
  989. CircleDefine()
  990. {
  991.     int i;
  992.     double theta, dtheta;
  993.  
  994.     dtheta = 2.*M_PI / (double)CIRCLE_SAMPLES;
  995.     CirclePoints = (float **)malloc(CIRCLE_SAMPLES * sizeof(float *));
  996.     for (i = 0, theta = 0; i < CIRCLE_SAMPLES; i++, theta += dtheta) {
  997.         CirclePoints[i] = (float *)malloc(3 * sizeof(float));
  998.         CirclePoints[i][0] = cos(theta);
  999.         CirclePoints[i][1] = sin(theta);
  1000.         /* Z is left unset. */    
  1001.     }
  1002. }
  1003.  
  1004. /*
  1005.  * Given world bounds, determine near and far
  1006.  * clipping planes.  Only problem occurs when there are
  1007.  * unbbounded objects (planes)...
  1008.  */
  1009. static void
  1010. ComputeClippingPlanes(near, far, bounds)
  1011. float *near, *far;
  1012. Float bounds[2][3];
  1013. {
  1014.     Vector e, c;
  1015.     double rad, d;
  1016.  
  1017.  
  1018.     /*
  1019.      * Compute 'radius' of scene.
  1020.      */
  1021.     rad = max(max((bounds[HIGH][X] - bounds[LOW][X])*0.5,
  1022.               (bounds[HIGH][Y] - bounds[LOW][Y])*0.5),
  1023.               (bounds[HIGH][Z] - bounds[LOW][Z])*0.5);
  1024.  
  1025.     c.x = (bounds[LOW][X] + bounds[HIGH][X])*0.5;
  1026.     c.y = (bounds[LOW][Y] + bounds[HIGH][Y])*0.5;
  1027.     c.z = (bounds[LOW][Z] + bounds[HIGH][Z])*0.5;
  1028.  
  1029.     /*
  1030.      * Compute position of eye relative to the center of the sphere.
  1031.      */
  1032.     VecSub(Camera.pos, c, &e);
  1033.     d = VecNormalize(&e);
  1034.     if (d <= rad)
  1035.         /*
  1036.          * Eye is inside sphere.
  1037.          */
  1038.         *near = DEFAULT_NEAR;
  1039.     else
  1040.         *near = (d - rad)*0.2;
  1041.     *far = (d + rad)*2.;
  1042. }
  1043.